#include "affichage.hpp"

void initAffichage (affichage &aff, unsigned int nb_niveaux, bool verbose)
{
    for(unsigned int i = 0; i<nb_niveaux; i++)
        ajoutNiveau(aff, "", verbose);
}

void ajoutNiveau (affichage &aff, string chaine, bool verbose)
{
    if (verbose)
        cout << "avant pushback size niveau = " << aff.niveau.size() << endl;
    aff.niveau.push_back(chaine);
    if (verbose)
    {
        cout << "apres affectation size niveau = " << aff.niveau.size() << endl;
        cout << "chaine ajoutée : " << aff.niveau[aff.niveau.size()-1] << endl;
    }
}

void affichageHorizontal(const arbre &a)
{
    cout << "affichage horizontal de l'arbre" << endl;
    affichageArbreHorizontal(a);
}

void affichageArbreVertical(const arbre &a, bool verbose)
{
    cout << "affichage vertical de l'arbre" << endl;
    if(!arbreVide(a))
    {

        affichage aff;
        initAffichage(aff);

        if(verbose)
            cout << "affichage initialisé" << endl;

        aff = remplirAff(*racine(a), verbose);

        afficher(aff);

        testamentAffichage(aff);
    } else {
        cout << "l'arbre est vide" << endl;
    }
}

affichage remplirAff (const noeud &n, bool verbose)
{
    if (verbose)
        cout << "entrée dans remplirAff" << endl;
    //remplirChaine(aff, n.info, n.type, niveau, ecart);

    if (noeudFilsFeuille(n)) // si tous les noeuds de n sont des feuilles
    {
        if (verbose)
            cout << "tous les fils du noeud sont des feuilles" << endl;

        affichage aff;
        initAffichage(aff, 3, verbose);

        if(verbose)
            cout << "affichage initialisé" << endl;

        //unsigned int position_valeur = 0;

        if (verbose)
            cout << "remplissage des fils dans affichage" << endl;

        for(unsigned int i = 0; i<n.nbFils; i++)
        {
            if (verbose)
                cout << "passage de boucle : " <<  i << endl;
            if(i>0)
                aff.niveau[2].append("   ");
            remplirChaine(aff, n.fils[i]->info, n.fils[i]->type, 2, verbose);
        }

        if (verbose)
            cout << "contenu des fils stocké dans la structure d'affichage" << endl;

        unsigned int fils_restants = n.nbFils;
        for(unsigned int i = 0; i<aff.niveau[2].size()-1; i++)
        {
            if(aff.niveau[2].at(i+1) != ' ' && fils_restants == 1)
            {
                aff.niveau[1].append("\\");
                fils_restants --;
            }

            if(aff.niveau[2].at(i) != ' ')
            {
                if (fils_restants == n.nbFils)
                {
                    aff.niveau[1].append(" /");
                    i++;
                }
                else if (fils_restants >1 && fils_restants < n.nbFils)
                {
                    aff.niveau[1].append("|");
                }
                else
                {
                    aff.niveau[1].append(" ");
                }
                fils_restants --;
            }
            else
            {
                aff.niveau[1].append(" ");
            }
        }

        if (verbose)
            cout << "chaine des liens stockée dans la structure d'affichage" << endl;

        unsigned int slash = aff.niveau[1].find("/");
        unsigned int antislash = aff.niveau[1].find("\\");
        unsigned int pos_op = (slash + antislash) / 2;

        for(unsigned int i = 0; i<pos_op; i++)
        {
            aff.niveau[0].append(" ");
        }
        remplirChaine(aff, n.info, n.type, 0, verbose);
        for(unsigned int i = pos_op+1; i<aff.niveau[2].size(); i++)
        {
            aff.niveau[0].append(" ");
        }
        return aff;
    }
    else if (!noeudFeuille(n)) //si le noeud n'est pas une feuille et que tous ces fils ne sont pas des feuilles
    {
        if (verbose)
            cout << "le noeud n'est pas une feuille et que tous ces fils ne sont pas des feuilles" << endl;
        affichage aff = remplirAff(*(n.fils[0]), verbose);


        for(unsigned int i = 0; i<aff.niveau.size(); i++)
            aff.niveau[i].append(" ");

        for(unsigned int i = 1; i<n.nbFils; i++)
        {

            affichage aff2;
            aff2 = remplirAff(*(n.fils[i]), verbose);
            // on met aff et aff2 à la même taille
            if(aff.niveau.size() < aff2.niveau.size())
            {
                string espace;
                for(unsigned int j = 0; j<aff.niveau[0].size(); j++)
                    espace.append(" ");

                while (aff.niveau.size() < aff2.niveau.size())
                {
                    ajoutNiveau(aff, espace);
                }
            }
            else if (aff.niveau.size() > aff2.niveau.size())
            {
                string espace;
                for(unsigned int j = 0; j<aff2.niveau[0].size(); j++)
                    espace.append(" ");

                while (aff.niveau.size() > aff2.niveau.size())
                {
                    ajoutNiveau(aff2, espace);
                }
            }


            for(unsigned int j = 0; j<aff.niveau.size(); j++)
            {
                aff.niveau[j].append(aff2.niveau[j]);
            }
            testamentAffichage(aff2);

            if(i != n.nbFils - 1)
            {
                for(unsigned int j = 0; j<aff.niveau.size(); j++)
                    aff.niveau[j].append(" ");
            }
        }

        affichage retour;
        initAffichage(retour, aff.niveau.size()+2);

        unsigned int fils_restants = n.nbFils;
        for(unsigned int i = 0; i<aff.niveau[0].size()-1; i++)
        {
            if(aff.niveau[0].at(i+1) != ' ' && fils_restants == 1)
            {
                retour.niveau[1].append("\\");
                fils_restants --;
            }

            if(aff.niveau[0].at(i) != ' ')
            {
                if (fils_restants == n.nbFils)
                {
                    retour.niveau[1].append(" /");
                    i++;
                }
                else if (fils_restants >1 && fils_restants < n.nbFils)
                {
                    retour.niveau[1].append("|");
                }
                else
                {
                    retour.niveau[1].append(" ");
                }
                fils_restants --;
            }
            else
            {
                retour.niveau[1].append(" ");
            }
        }
        if(verbose)
            cout << "taille de la chaine des liens : " << retour.niveau[1].size() << endl;

        // on ajoute l'opérateur entre le / et le antislash
        unsigned int slash = retour.niveau[1].find("/");
        unsigned int antislash = retour.niveau[1].find("\\");
        unsigned int pos_op = (slash + antislash) / 2;

        for(unsigned int i = 0; i<pos_op; i++)
        {
            retour.niveau[0].append(" ");
        }
        remplirChaine(retour, n.info, n.type, 0, verbose);
        for(unsigned int i = pos_op+1; i<aff.niveau[0].size(); i++)
        {
            retour.niveau[0].append(" ");
        }

        for (unsigned int i = 0; i<aff.niveau.size(); i++)
        {
            retour.niveau[i+2].append(aff.niveau[i]);
        }

        testamentAffichage(aff);
        return retour;
    }
    else // le dernier cas est que le noeud est une feuille
    {
        if (verbose)
            cout << "le noeud est une feuille simple" << endl;

        affichage aff;
        initAffichage(aff, 1, verbose);
        remplirChaine(aff, n.info, n.type, 0, verbose);
        return aff;
    }
}

void remplirChaine (affichage &aff, const elt element, const e_type type, unsigned int niveau, bool verbose)
{
    if (verbose)
        cout << "\tentrée dans remplir chaine" << endl;

    switch (type) {
        case t_operateur:
            if (verbose)
                cout << "\tle noeud contient un opérateur" << endl;
            remplirOperateur(aff, element.op, niveau, verbose);
            break;

        case t_valeur:
            if (verbose)
                cout << "\tle noeud contient une valeur" << endl;
            remplirValeur(aff, element.valeur, niveau, verbose);
            break;

        default:
            break;
    }
}

void remplirOperateur (affichage &aff, const operateur op, unsigned int niveau, bool verbose)
{
    if(verbose)
        cout << "\tl'operateur à afficher au niveau " << niveau << " est un ";
    switch (op) {
        case o_plus :
            if (verbose)
                cout << "+" << endl;
            aff.niveau[niveau].append("+");
            break;

        case o_mult :
            if (verbose)
                cout << "*" << endl;
            aff.niveau[niveau].append("*");
            break;
    }
    if(verbose)
        cout << "\tl'operateur est stocké dans la structure d'affichage";
}

void remplirValeur (affichage &aff, const int valeur, unsigned int niveau, bool verbose)
{
    char* c = new char;
    sprintf(c, "%d", valeur);
    if (verbose)
        cout << "\tla valeur à afficher est " << c  << " au niveau " << niveau << endl;
    aff.niveau[niveau].append(c);
    if(verbose)
        cout << "\tla valeur est stockée dans la structure d'affichage" << endl;
    delete(c);
}

void afficher(affichage &aff)
{
    for(unsigned int i= 0; i<aff.niveau.size(); i++)
    {
        if(aff.niveau[i].compare("") != 0) // chaine vide
            cout << aff.niveau[i] << endl;
    }
    cout << endl;
}


void testamentAffichage(affichage &aff)
{

}
